import xmlrpc.client as  xmlrpclib
from time import sleep

from django.conf import settings
from django.core.cache import cache

import os, sys

parent_path = os.path.dirname(os.getcwd())
sys.path.append(os.path.dirname(parent_path))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cronmanger.settings")
import django

django.setup()
from supervisor_dj.models import SupervisorHost, Supervisor_Process

SUPERVISOR_PASS = settings.SUPERVISOR_PASS
SUPERVISOR_USER = settings.SUPERVISOR_USER

SUPER_SUCCESS = (0, "SUCCESS")
CONN_ERR = 1
START_ERR = 2
STOP_ERR = 3
RESTART_ERR = 4
GET_ONE_ERR = 5
GET_ALL_ERR = 6
GET_STATUS_ERR = 7
GENERAL_ERR = 8


class SupervisorClass:
    msg = {"status_code": 0, "msg": None}

    def __init__(self, username=SUPERVISOR_USER, password=SUPERVISOR_PASS, ip=None, port=None):
        self.username = username
        self.password = password
        self.ip = ip
        self.port = port if port else 9001

    def supervisor_obj(self):
        supervisor_obj = self.get_connecti(self.ip, self.port, self.username, self.password).supervisor
        return supervisor_obj

    def get_connecti(self, ip=None, port=None, username=None, password=None):
        """
        :param ip:
        :param port:
        :param username:
        :param password:
        :return:  返回连接对象     server = xmlrpclib.Server('http://zrd:sh123!@192.168.1.60:9001/RPC2/')
        """

        if username and password:
            # 有密码和账号
            connection_info = f'http://{username}:{password}@{ip}:{port}/RPC2/'
            server = xmlrpclib.Server(connection_info)
            return server

        # 无密码和账号
        connection_info_no_pass = f'http://{ip}:{port}/RPC2/'
        return xmlrpclib.Server(connection_info_no_pass)

    def start(self, ip=None, process_name=None):
        """
        启动进程
        :param ip:
        :param process_name:
        :return:
        """
        if ip:
            self.ip = ip
        try:
            # 查询进程运行状态
            obj = Supervisor_Process.objects.filter(name=process_name, ip=self.ip).first()
            obj_supervisor_host = obj.supervisor_host
            process_status = obj.detail.get('statename', None)
            if process_status == 'RUNNING':
                # 判断进程是否是已运行
                self.msg['status_code'] = GENERAL_ERR
                self.msg["msg"] = f"{process_name} 已是运行状态"
                return self.msg

            # 启动进程
            rst = self.supervisor_obj().startProcess(process_name)
            if rst == True:
                self.msg["status_code"] = 0
                self.msg['msg'] = f"启动{process_name}进程成功"
                # 查询进程运行状态
                process_info = self.get_a_process_info(process_name=process_name)
                # 刷新信息到数据库
                Supervisor_Process.objects.update_or_create(
                    ip=self.ip,
                    process_name=process_name,
                    detail=process_info,
                    supervisor_host=obj_supervisor_host)
                return self.msg
        except xmlrpclib.Fault  as e:
            self.msg["status_code"] = START_ERR
            self.msg['msg'] = e.faultString
            return self.msg
        except Exception as e:
            self.msg["status_code"] = START_ERR
            self.msg['msg'] = e.args
            return self.msg

    def stop(self, ip=None, process_name=None):
        """
        停止进程
        :param ip:
        :param process_name:
        :return:
        """
        self.ip = ip if ip else self.ip
        try:
            # 查询进程运行状态
            obj = Supervisor_Process.objects.filter(name=process_name, ip=self.ip).first()
            obj_supervisor_host = obj.supervisor_host
            process_status = obj.detail.get('statename', None)
            if process_status == 'STOPPED':
                self.msg['status_code'] = GENERAL_ERR
                self.msg["msg"] = f"{process_name} 已是STOPPED状态"
                return self.msg

            # 停止进程
            rst = self.supervisor_obj().stopProcess(process_name)
            if rst == True:
                self.msg["status_code"] = 0
                self.msg['msg'] = f"启动{process_name}进程成功"
                # 查询进程运行状态
                process_info = self.get_a_process_info(process_name=process_name)
                # 刷新信息到数据库
                Supervisor_Process.objects.update_or_create(
                    ip=self.ip,
                    process_name=process_name,
                    detail=process_info,
                    supervisor_host=obj_supervisor_host)
                return self.msg
        except xmlrpclib.Fault  as e:
            self.msg["status_code"] = STOP_ERR
            self.msg['msg'] = e.faultString
            return self.msg
        except Exception as e:
            self.msg["status_code"] = STOP_ERR
            self.msg['msg'] = e.args
            return self.msg

    def restart(self, ip=None, process_name=None, ):
        """
        重启进程
        :param p_name:
        :return:
        """
        self.ip = ip if ip else self.ip
        # 查询进程运行状态
        obj = Supervisor_Process.objects.filter(name=process_name, ip=self.ip).first()
        obj_supervisor_host = obj.supervisor_host
        process_status = obj.detail.get('statename', None)
        if process_status == 'RUNNING':
            self.stop(ip=self.ip, process_name=process_name)
            sleep(1)
            if self.msg["status_code"] != 0:
                return self.msg
        start = self.start(ip=self.ip, process_name=process_name)
        return self.msg

    def get_a_process_info(self, process_name=None):
        """
        获取管理进程详情 (一个进程信息)
        :param process_name:
        :return:   {process......}
        """
        try:
            return self.supervisor_obj().getProcessInfo(process_name)
        except xmlrpclib.Fault as e:
            self.msg['status_code'] = GET_STATUS_ERR
            self.msg['msg'] = e.faultString
        except Exception as e:
            self.msg['status_code'] = GET_STATUS_ERR
            self.msg['msg'] = e.args

    def get_all_processes_info(self, ip=None):
        """
        获取一台主机上所有被管理的进程
        :param ip:
        :return:     [{proces1}，{process2}, .....]
        """
        self.ip = ip if ip else self.ip

        try:
            all_process_list = self.supervisor_obj().getAllProcessInfo()
            return all_process_list
        except  xmlrpclib.Fault as e:
            self.msg['status_code'] = GET_ALL_ERR
            self.msg['msg'] = e.faultString
            return self.msg
        except Exception as e:
            self.msg['status_code'] = GET_ALL_ERR
            self.msg['msg'] = e.args
            return self.msg

    def write_to_mysql(self, ip=None, process_name=None, detail=None):
        """
        进程信息写入数据库
        :param ip:
        :param process_name:
        :param detail:
        :return:
        """
        self.ip = ip if ip else self.ip

        s_obj = Supervisor_Process.objects.filter(ip=self.ip, name=process_name)
        if s_obj.exists():
            s_obj = s_obj.first()
        s_obj.update_or_create(ip=ip, process_name=process_name, detail=detail)

    def refresh_all_process_info(self):
        # 1、清空数据库所有进程信息
        Supervisor_Process.objects.all().delete()
        # 2、查出所有主机
        host_obj = SupervisorHost.objects.all()
        # 批量插入
        insert_bulk_list = []
        for host in host_obj:
            ip = host.ip
            # 3、获取此ip对应主机上所有进程
            all = self.get_all_processes_info(ip=ip)
            print(all)
            if self.msg['status_code'] != 0:
                return self.msg
            for process in all:
                process_name = process['name']
                # 实例化一个进程详情
                s = Supervisor_Process(name=process_name, ip=ip, detail=process, supervisor_host=host)
                insert_bulk_list.append(s)
        # 批量插入
        Supervisor_Process.objects.bulk_create(insert_bulk_list, batch_size=100)


"""
启动进程
    1、获取进程运行状态，如果进程本身就是运行态则报错
停止进程
    2、。。。。。。。。，如果是停止态则报错

{
'description': 'pid 8422, uptime 1 day, 18:49:59',
'pid': 8422, 
'stderr_logfile': '', 
'stop': 1521880185,
'logfile': '/tmp/python_amon_gunicorn.log',
'exitstatus': 0,
'spawnerr': '',
'now': 1522036704,
'group': 'python_amon_gunicorn',
'name': 'python_amon_gunicorn', 
'statename': 'RUNNING',
'start': 1521882505, 
'state': 20, 'stdout_logfile': '/tmp/python_amon_gunicorn.log'
}
"""

if __name__ == '__main__':
    s = SupervisorClass()
    # 测试清空刷新所有进程信息
    s.refresh_all_process_info()

    # s.restart(ip='192.168.1.60', process_name='zrd_mongod')
